package com.imut.lagain.controller;

import com.imut.lagain.entity.User;
import com.imut.lagain.entity.UserRole;
import com.imut.lagain.service.IUserService;
import com.imut.lagain.service.IUserRoleService;
import com.imut.lagain.service.IWeChatService;
import com.imut.lagain.service.NotificationService;
import com.imut.lagain.util.JwtUtil;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.Pattern;

/**
 * 认证控制器
 */
@RestController
@RequestMapping("/auth")
@Validated
public class AuthController {

    private static final Logger log = LoggerFactory.getLogger(AuthController.class);

    private final IWeChatService weChatService;
    private final IUserService userService;
    private final IUserRoleService userRoleService;
    private final JwtUtil jwtUtil;
    private final NotificationService notificationService;
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Autowired
    public AuthController(IUserService userService, 
                          IUserRoleService userRoleService, 
                          JwtUtil jwtUtil, 
                          NotificationService notificationService,
                          IWeChatService weChatService) {
        this.userService = userService;
        this.userRoleService = userRoleService;
        this.jwtUtil = jwtUtil;
        this.notificationService = notificationService;
        this.weChatService = weChatService;
    }

    /**
     * 微信登录（包括手机号登录）
     * @param loginRequest 登录请求
     * @return 登录结果
     */
    @PostMapping("/wx-login")
    public ResponseEntity<Map<String, Object>> wxLogin(@Valid @RequestBody WxLoginRequest loginRequest) {
        log.info("=== 收到微信登录请求 ===");
        log.info("请求URL: /api/auth/wx-login");
        log.info("请求参数: code={}, hasEncryptedData={}", 
            loginRequest.getCode(), loginRequest.getEncryptedData() != null);
        
        Map<String, Object> response = new HashMap<>();
        
        // 检查微信服务是否可用
        log.info("检查微信服务是否可用: weChatService={}", weChatService != null);
        if (weChatService == null) {
            log.warn("微信服务未配置");
            response.put("success", false);
            response.put("message", "微信服务未配置");
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(response);
        }
        
        try {
            log.info("1. 通过code获取session信息");
            Map<String, String> sessionInfo = weChatService.getSessionInfo(loginRequest.getCode());
            log.info("获取session信息结果: {}", sessionInfo);
            
            if (sessionInfo == null) {
                log.warn("获取微信session失败: sessionInfo=null");
                response.put("success", false);
                response.put("message", "获取微信session失败");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 检查是否有错误码
            if (sessionInfo.containsKey("errcode") && !"0".equals(sessionInfo.get("errcode"))) {
                String errCode = sessionInfo.get("errcode");
                String errMsg = sessionInfo.get("errmsg");
                log.error("微信登录失败，错误码: {}，错误信息: {}", errCode, errMsg);
                
                // 根据错误码返回不同的响应
                switch (errCode) {
                    case "40013":
                        response.put("success", false);
                        response.put("message", "AppID无效");
                        return ResponseEntity.badRequest().body(response);
                    case "40125":
                        response.put("success", false);
                        response.put("message", "AppSecret无效");
                        return ResponseEntity.badRequest().body(response);
                    case "40029":
                        response.put("success", false);
                        response.put("message", "code无效");
                        return ResponseEntity.badRequest().body(response);
                    case "45011":
                        response.put("success", false);
                        response.put("message", "API调用太频繁，请稍后再试");
                        return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body(response);
                    default:
                        response.put("success", false);
                        response.put("message", "微信登录失败: " + errMsg);
                        return ResponseEntity.badRequest().body(response);
                }
            }
            
            String openid = sessionInfo.get("openid");
            String sessionKey = sessionInfo.get("session_key");
            log.info("获取到openid: {}, sessionKey长度: {}", openid, sessionKey != null ? sessionKey.length() : 0);
            
            // 如果请求中包含手机号加密数据，则进行手机号解密
            if (loginRequest.getEncryptedData() != null && loginRequest.getIv() != null) {
                log.info("2. 解密手机号信息");
                Map<String, Object> phoneInfo = weChatService.decryptPhoneNumber(
                    loginRequest.getEncryptedData(), 
                    loginRequest.getIv(), 
                    sessionKey);
                log.info("手机号解密结果: {}", phoneInfo);
                
                if (phoneInfo.containsKey("errcode") && (Integer) phoneInfo.get("errcode") != 0) {
                    log.error("手机号解密失败: {}", phoneInfo.get("errmsg"));
                    response.put("success", false);
                    response.put("message", "手机号解密失败: " + phoneInfo.get("errmsg"));
                    return ResponseEntity.badRequest().body(response);
                }
                
                String phoneNumber = (String) phoneInfo.get("phoneNumber");
                log.info("解密得到手机号: {}", phoneNumber);
                
                // 根据手机号查找用户
                User user = userService.getUserByPhone(phoneNumber);
                log.info("根据手机号查找用户结果: user={}", user);
                
                if (user == null) {
                    log.warn("手机号未注册: {}", phoneNumber);
                    response.put("success", false);
                    response.put("code", 404);
                    response.put("message", "该手机号未注册，请先注册");
                    return ResponseEntity.ok(response);
                }
                
                // 获取用户角色信息
                UserRole userRole = userRoleService.getUserRole(user.getId());
                log.info("获取用户角色信息结果: userRole={}", userRole);
                
                if (userRole == null) {
                    log.warn("用户角色不存在: userId={}", user.getId());
                    response.put("success", false);
                    response.put("message", "用户角色配置错误");
                    return ResponseEntity.ok(response);
                }
                
                // 检查用户状态
                if (!user.getIsActive()) {
                    log.warn("用户已被禁用: phone={}", phoneNumber);
                    response.put("success", false);
                    response.put("message", "账号已被禁用");
                    return ResponseEntity.ok(response);
                }
                
                if (!userRole.getIsActive()) {
                    log.warn("用户角色已被禁用: phone={}", phoneNumber);
                    response.put("success", false);
                    response.put("message", "账号权限已被禁用");
                    return ResponseEntity.ok(response);
                }
                
                // 更新用户微信信息
                user.setOpenid(openid);
                if (sessionInfo.containsKey("unionid")) {
                    user.setUnionid(sessionInfo.get("unionid"));
                }
                if (loginRequest.getNickname() != null) {
                    user.setNickname(loginRequest.getNickname());
                }
                if (loginRequest.getAvatarUrl() != null) {
                    user.setAvatarUrl(loginRequest.getAvatarUrl());
                }
                
                try {
                    boolean updateResult = userService.updateById(user);
                    if (!updateResult) {
                        log.error("更新用户微信信息失败");
                        response.put("success", false);
                        response.put("message", "更新用户信息失败");
                        return ResponseEntity.internalServerError().body(response);
                    }
                    log.info("更新用户微信信息完成");
                } catch (Exception e) {
                    log.error("更新用户信息异常: ", e);
                    response.put("success", false);
                    response.put("message", "更新用户信息异常: " + e.getMessage());
                    return ResponseEntity.internalServerError().body(response);
                }

                // 生成JWT令牌
                String token = jwtUtil.generateToken(user.getId(), user.getOpenid());
                log.info("生成JWT令牌完成");
                
                // 构建返回数据
                response.put("success", true);
                response.put("message", "登录成功");
                response.put("token", token);
                response.put("user", user);
                response.put("role", userRole.getRoleType());
                response.put("roleName", userRole.getRoleName());
                
                log.info("用户通过微信手机号登录成功: userId={}, phone={}, role={}", 
                        user.getId(), phoneNumber, userRole.getRoleType());
                
                // 记录用户操作
                notificationService.recordUserAction(user, "LOGIN", 
                        String.format("用户通过微信一键登录系统，角色: %s", userRole.getRoleName()));
                
                return ResponseEntity.ok(response);
            } else {
                // 普通微信登录
                log.info("2. 查找或创建用户");
                User user = userService.getOrCreateUser(openid, 
                    sessionInfo.containsKey("unionid") ? sessionInfo.get("unionid") : null,
                    loginRequest.getNickname(), loginRequest.getAvatarUrl(), null);
                
                if (user == null) {
                    log.error("创建或查找用户失败");
                    response.put("success", false);
                    response.put("message", "创建或查找用户失败");
                    return ResponseEntity.internalServerError().body(response);
                }
                
                log.info("查找或创建用户结果: user={}", user);

                // 检查用户是否绑定了手机号
                if (user.getPhone() == null || user.getPhone().isEmpty()) {
                    log.info("用户未绑定手机号: userId={}", user.getId());
                    response.put("success", false);
                    response.put("message", "请先绑定手机号");
                    response.put("requirePhone", true);
                    response.put("user", user);
                    return ResponseEntity.ok(response);
                }
                
                // 获取用户角色信息
                UserRole userRole = userRoleService.getUserRole(user.getId());
                log.info("获取用户角色信息结果: userRole={}", userRole);
                
                if (userRole == null) {
                    log.warn("用户角色不存在: userId={}", user.getId());
                    response.put("success", false);
                    response.put("message", "用户角色配置错误");
                    return ResponseEntity.ok(response);
                }
                
                // 检查用户状态
                if (!user.getIsActive()) {
                    log.warn("用户已被禁用: userId={}", user.getId());
                    response.put("success", false);
                    response.put("message", "账号已被禁用");
                    return ResponseEntity.ok(response);
                }
                
                if (!userRole.getIsActive()) {
                    log.warn("用户角色已被禁用: userId={}", user.getId());
                    response.put("success", false);
                    response.put("message", "账号权限已被禁用");
                    return ResponseEntity.ok(response);
                }
                
                // 生成JWT令牌
                String token = jwtUtil.generateToken(user.getId(), user.getOpenid());
                log.info("生成JWT令牌完成");
                
                // 构建返回数据
                response.put("success", true);
                response.put("message", "登录成功");
                response.put("token", token);
                response.put("user", user);
                response.put("role", userRole.getRoleType());
                response.put("roleName", userRole.getRoleName());
                
                log.info("用户通过微信普通登录成功: userId={}, role={}", 
                        user.getId(), userRole.getRoleType());
                
                // 记录用户操作
                notificationService.recordUserAction(user, "LOGIN", 
                        String.format("用户通过微信普通登录系统，角色: %s", userRole.getRoleName()));
                
                return ResponseEntity.ok(response);
            }
        } catch (Exception e) {
            log.error("微信登录失败", e);
            response.put("success", false);
            response.put("message", "登录失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }

    /**
     * 验证Token
     * @param token JWT令牌
     * @return 验证结果
     */
    @PostMapping("/verify-token")
    public ResponseEntity<Map<String, Object>> verifyToken(@NotBlank(message = "Token不能为空") @RequestParam String token) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            if (jwtUtil.validateToken(token)) {
                Long userId = jwtUtil.getUserIdFromToken(token);
                User user = userService.getById(userId);
                
                if (user != null) {
                    response.put("success", true);
                    response.put("message", "Token验证成功");
                    response.put("user", user);
                    return ResponseEntity.ok(response);
                } else {
                    response.put("success", false);
                    response.put("message", "用户不存在");
                    return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
                }
            } else {
                response.put("success", false);
                response.put("message", "Token无效或已过期");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }
        } catch (Exception e) {
            log.error("Token验证失败", e);
            response.put("success", false);
            response.put("message", "Token验证失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }

    /**
     * 微信登录请求DTO
     */
    public static class WxLoginRequest {
        @NotBlank(message = "微信授权码不能为空")
        private String code;
        
        private String encryptedData;
        
        private String iv;
        
        @Size(min = 1, max = 50, message = "昵称长度必须在1-50之间")
        private String nickname;
        
        @Pattern(regexp = "^https?://.*\\.(jpg|jpeg|png|gif|webp)$", message = "头像URL格式不正确")
        private String avatarUrl;
        
        public String getCode() {
            return code;
        }
        
        public void setCode(String code) {
            this.code = code;
        }
        
        public String getEncryptedData() {
            return encryptedData;
        }
        
        public void setEncryptedData(String encryptedData) {
            this.encryptedData = encryptedData;
        }
        
        public String getIv() {
            return iv;
        }
        
        public void setIv(String iv) {
            this.iv = iv;
        }
        
        public String getNickname() {
            return nickname;
        }
        
        public void setNickname(String nickname) {
            this.nickname = nickname;
        }
        
        public String getAvatarUrl() {
            return avatarUrl;
        }
        
        public void setAvatarUrl(String avatarUrl) {
            this.avatarUrl = avatarUrl;
        }
    }
}